home *** CD-ROM | disk | FTP | other *** search
- /*
-
- Name:
- LOAD_ULT.C
-
- Description:
- Ultratracker (ULT) module loader
-
- Portability:
- All systems - all compilers (hopefully)
-
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include "mikmod.h"
-
- #define ULTS_16BITS 4
- #define ULTS_LOOP 8
- #define ULTS_REVERSE 16
-
-
- /* Raw ULT header struct: */
-
- typedef struct ULTHEADER{
- char id[15];
- char songtitle[32];
- UBYTE reserved;
- } ULTHEADER;
-
-
- /* Raw ULT sampleinfo struct: */
-
- typedef struct ULTSAMPLE{
- char samplename[32];
- char dosname[12];
- SLONG loopstart;
- SLONG loopend;
- SLONG sizestart;
- SLONG sizeend;
- UBYTE volume;
- UBYTE flags;
- SWORD finetune;
- } ULTSAMPLE;
-
-
- typedef struct ULTEVENT{
- UBYTE note,sample,eff,dat1,dat2;
- } ULTEVENT;
-
-
- char *ULT_Version[]={
- "Ultra Tracker V1.3",
- "Ultra Tracker V1.4",
- "Ultra Tracker V1.5",
- "Ultra Tracker V1.6"
- };
-
-
- BOOL ULT_Test(void)
- {
- char id[15];
-
- if(!fread(&id,15,1,modfp)) return 0;
- return(!strncmp(id,"MAS_UTrack_V00",14));
- }
-
-
- BOOL ULT_Init(void)
- {
- return 1;
- }
-
-
- void ULT_Cleanup(void)
- {
- }
-
- ULTEVENT ev;
-
-
-
- int ReadUltEvent(ULTEVENT *event)
- {
- UBYTE flag,rep=1;
-
- flag=_mm_read_UBYTE(modfp);
-
- if(flag==0xfc){
- fread(&rep,1,1,modfp);
- event->note =_mm_read_UBYTE(modfp);
- }
- else{
- event->note=flag;
- }
-
- event->sample =_mm_read_UBYTE(modfp);
- event->eff =_mm_read_UBYTE(modfp);
- event->dat1 =_mm_read_UBYTE(modfp);
- event->dat2 =_mm_read_UBYTE(modfp);
-
- return rep;
- }
-
-
-
-
- BOOL ULT_Load(void)
- {
- int t,u,tracks=0;
- INSTRUMENT *d;
- SAMPLE *q;
- ULTSAMPLE s;
- ULTHEADER mh;
- UBYTE nos,noc,nop;
-
- /* try to read module header */
-
- _mm_read_str(mh.id,15,modfp);
- _mm_read_str(mh.songtitle,32,modfp);
- mh.reserved=_mm_read_UBYTE(modfp);
-
- if(feof(modfp)){
- myerr=ERROR_LOADING_HEADER;
- return 0;
- }
-
- if(mh.id[14]<'1' || mh.id[14]>'4'){
- printf("This version is not yet supported\n");
- return 0;
- }
-
- of.modtype=strdup(ULT_Version[mh.id[14]-'1']);
- of.initspeed=6;
- of.inittempo=125;
-
- /* read songtext */
-
- if(!ReadComment((UWORD)mh.reserved*32)) return 0;
-
- nos=_mm_read_UBYTE(modfp);
-
- if(feof(modfp)){
- myerr=ERROR_LOADING_HEADER;
- return 0;
- }
-
- of.songname=DupStr(mh.songtitle,32);
- of.numins=nos;
-
- if(!AllocInstruments()) return 0;
-
- d=of.instruments;
-
- for(t=0;t<nos;t++){
-
- d->numsmp=1;
- if(!AllocSamples(d)) return 0;
- q=d->samples;
-
- /* try to read sample info */
-
- _mm_read_str(s.samplename,32,modfp);
- _mm_read_str(s.dosname,12,modfp);
- s.loopstart =_mm_read_I_ULONG(modfp);
- s.loopend =_mm_read_I_ULONG(modfp);
- s.sizestart =_mm_read_I_ULONG(modfp);
- s.sizeend =_mm_read_I_ULONG(modfp);
- s.volume =_mm_read_UBYTE(modfp);
- s.flags =_mm_read_UBYTE(modfp);
- s.finetune =_mm_read_I_SWORD(modfp);
-
- if(feof(modfp)){
- myerr=ERROR_LOADING_SAMPLEINFO;
- return 0;
- }
-
- d->insname=DupStr(s.samplename,32);
-
- q->seekpos=0;
-
- q->c2spd=8363;
-
- if(mh.id[14]>='4'){
- _mm_read_I_UWORD(modfp); /* read 1.6 extra info(??) word */
- q->c2spd=s.finetune;
- }
-
- q->length=s.sizeend-s.sizestart;
- q->volume=s.volume>>2;
- q->loopstart=s.loopstart;
- q->loopend=s.loopend;
-
- q->flags=SF_SIGNED;
-
- if(s.flags&ULTS_LOOP){
- q->flags|=SF_LOOP;
- }
-
- if(s.flags&ULTS_16BITS){
- q->flags|=SF_16BITS;
- q->loopstart>>=1;
- q->loopend>>=1;
- }
-
- /* printf("Sample %d %s length %ld\n",t,d->samplename,d->length); */
- d++;
- }
-
- _mm_read_UBYTES(of.positions,256,modfp);
-
- for(t=0;t<256;t++){
- if(of.positions[t]==255) break;
- }
- of.numpos=t;
-
- noc=_mm_read_UBYTE(modfp);
- nop=_mm_read_UBYTE(modfp);
-
- of.numchn=noc+1;
- of.numpat=nop+1;
- of.numtrk=of.numchn*of.numpat;
-
- if(!AllocTracks()) return 0;
- if(!AllocPatterns()) return 0;
-
- for(u=0;u<of.numchn;u++){
- for(t=0;t<of.numpat;t++){
- of.patterns[(t*of.numchn)+u]=tracks++;
- }
- }
-
- /* read pan position table for v1.5 and higher */
-
- if(mh.id[14]>='3'){
- for(t=0;t<of.numchn;t++) of.panning[t]=_mm_read_UBYTE(modfp)<<4;
- }
-
-
- for(t=0;t<of.numtrk;t++){
- int rep,s,done;
-
- UniReset();
- done=0;
-
- while(done<64){
-
- rep=ReadUltEvent(&ev);
-
- if(feof(modfp)){
- myerr=ERROR_LOADING_TRACK;
- return 0;
- }
-
- /* printf("rep %d: n %d i %d e %x d1 %d d2 %d \n",rep,ev.note,ev.sample,ev.eff,ev.dat1,ev.dat2); */
-
-
- for(s=0;s<rep;s++){
- UBYTE eff;
-
-
- if(ev.sample){
- UniInstrument(ev.sample-1);
- }
-
- if(ev.note){
- UniNote(ev.note+23);
- }
-
- eff=ev.eff>>4;
-
-
- /*
- ULT panning effect fixed by Alexander Kerkhove :
- */
-
-
- if(eff==0xc) UniPTEffect(eff,ev.dat2>>2);
- else if(eff==0xb) UniPTEffect(8,ev.dat2*0xf);
- else UniPTEffect(eff,ev.dat2);
-
- eff=ev.eff&0xf;
-
- if(eff==0xc) UniPTEffect(eff,ev.dat1>>2);
- else if(eff==0xb) UniPTEffect(8,ev.dat1*0xf);
- else UniPTEffect(eff,ev.dat1);
-
- UniNewline();
- done++;
- }
- }
- /* printf("----------------"); */
-
- if(!(of.tracks[t]=UniDup())) return 0;
- }
-
- /* printf("%d channels %d patterns\n",of.numchn,of.numpat); */
- /* printf("Song %32.32s: There's %d samples\n",mh.songtitle,nos); */
- return 1;
- }
-
-
-
- LOADER load_ult={
- NULL,
- "ULT",
- "Portable ULT loader v0.1",
- ULT_Init,
- ULT_Test,
- ULT_Load,
- ULT_Cleanup
- };
-